import os
import json
import random
import argparse
from moviepy.editor import *
from datetime import datetime


def get_file_name_without_extension(file_path):
    # 获取文件名和扩展名
    file_name, _ = os.path.splitext(os.path.basename(file_path))
    # 返回不带扩展名的文件名
    return file_name

# 替换以下占位符为实际文件夹路径
def is_empty_directory(directory_path):
    if not os.path.exists(directory_path):
        raise FileNotFoundError(f"目录不存在：{directory_path}")

    if not os.path.isdir(directory_path):
        raise ValueError(f"给定的路径不是目录：{directory_path}")

    return len(os.listdir(directory_path)) == 0

def func_video_split():
    # 解析命令行参数
    parser = argparse.ArgumentParser(description="从指定目录中随机挑选片段，组合成指定长度的视频片段。")
    parser.add_argument("-iv", "--video_path", type=str, default="input", help="视频文件路径，默认为空。")
    parser.add_argument("-ov", "--output_video_path", type=str, default="clips_video", help="输出文件路径，默认为空。")
    parser.add_argument("-oa", "--output_audio_path", type=str, default="clips_audio", help="输出文件路径，默认为空。")
    parser.add_argument("-min", "--target_min_duration", type=int, default=1, help="最小输出片段市场，默认及最小1秒。")
    parser.add_argument("-max", "--target_max_duration", type=int, default=3, help="最大输出片段市场，默认3秒。")
    parser.add_argument("-wa", "--output_video_with_audio", type=int,default=1, help="输出视频是否带上原音频。")
    parser.add_argument("-ev", "--output_video_enable", type=int,default=1, help="是否输出片段视频。")
    parser.add_argument("-ea", "--output_audio_enable", type=int,default=1, help="是否输出片段音频。")
    parser.add_argument("-eta", "--output_total_audio_enable", type=int,default=1, help="输出输出完整音频。")
    parser.add_argument("-vw", "--width", type=int, default=720, help="输出视频宽度，默认为1280像素。")
    parser.add_argument("-vh", "--height", type=int, default=1280, help="输出视频高度，默认为720像素。")
    parser.add_argument("-qv", "--quality", type=int, default=3, help="视频质量，默认为3。")
    args = parser.parse_args()

    # 替换以下占位符为实际文件夹路径
    input_directory = args.video_path
    output_video_directory = args.output_video_path
    output_audio_directory = args.output_audio_path

    # 确保文件夹路径有效
    if not os.path.exists(input_directory):
        raise FileNotFoundError(f"视频文件夹不存在：{input_directory}")

    if is_empty_directory(input_directory):
        raise ValueError(f"视频文件夹为空：{input_directory}")

    if not os.path.exists(output_video_directory):
        os.makedirs(output_video_directory)

    if not os.path.exists(output_audio_directory):
        os.makedirs(output_audio_directory)

    # 获取目录中的所有视频文件
    video_files = [f for f in os.listdir(input_directory) if f.endswith(('.mp4', '.avi', '.mkv'))]

    # 设置preset值以控制编码速度和压缩效果
    preset_values=["ultrafast","superfast","veryfast","faster","fast","medium","slow","slower","veryslow"]
    preset_index=args.quality
    if preset_index<0 or preset_index>=len(preset_values):
        preset_index=len(preset_values)-1
    preset_value=preset_values[preset_index]
    print("视频质量：",preset_value)
    t_min=args.target_min_duration
    if t_min<1:
     t_min=1
    t_max=args.target_max_duration   
    print("片段最小时长",t_min)
    print("片段最大时长",t_max)

    # 切割视频并分别保存视频和音频
    for video_file in video_files:
        video_path = os.path.join(input_directory, video_file)
        video_clip = VideoFileClip(video_path)
        audio_clip = video_clip.audio

        file_name= get_file_name_without_extension(video_path)

        if args.output_total_audio_enable==1 and audio_clip is not None:
            # 是否输出完整音频
            current_time = datetime.now().strftime("%Y%m%d%H%M%S")
            output_audio_filename = f"{file_name}_total_{current_time}_{int(video_clip.duration)}s.mp3"
            audio_output_path = os.path.join(output_audio_directory, f"{output_audio_filename}")
            audio_clip.write_audiofile(audio_output_path, codec='libmp3lame')

        # 切割视频和音频
        video_duration=int(video_clip.duration)
        cur_total_duration=0
        while cur_total_duration<video_duration:
            current_time = datetime.now().strftime("%Y%m%d%H%M%S")

            # 随机选择一个片段时长
            target_duration = random.randint(t_min, t_max)
            if target_duration<t_min:
                # 最后一段不足最小值，跳出
                break

            start_time = cur_total_duration
            end_time = start_time+target_duration
            end_time = min(end_time,video_duration)

            cur_total_duration+=target_duration
            
            # 切割音频
            if audio_clip is not None:
                audio_segment = audio_clip.subclip(start_time, end_time)
                if args.output_audio_enable==1:
                    # 是否输出音频
                    output_audio_filename = f"{file_name}_{current_time}_{target_duration}s.mp3"
                    audio_output_path = os.path.join(output_audio_directory, f"{output_audio_filename}")
                    audio_segment.write_audiofile(audio_output_path, codec='libmp3lame')


            if args.output_video_enable==1:
                # 是否输出视频片段
                # 切割视频
                video_segment = video_clip.subclip(start_time, end_time).without_audio()
                # 将音频片段添加到视频片段中
                if args.output_video_with_audio==1 and audio_segment is not None:
                    video_segment = video_segment.set_audio(audio_segment)
                # 调整视频宽度和高度
                video_segment = video_segment.resize((args.width, args.height))
                output_video_filename = f"{file_name}_{current_time}_{target_duration}s.mp4"
                video_output_path = os.path.join(output_video_directory, f"{output_video_filename}")
                video_segment.write_videofile(video_output_path, codec='libx264',preset=preset_value)

            audio_segment=None
            print(f"已切割: {video_path}，片段: {start_time}-{end_time}")


    


def func_video_combine():
    # 解析命令行参数
    parser = argparse.ArgumentParser(description="从指定目录中随机挑选片段，组合成指定长度的视频片段。")
    parser.add_argument("-iv", "--video_path", type=str, default="clips_video", help="视频文件路径，默认为空。")
    parser.add_argument("-ia", "--audio_path", type=str, default="clips_audio", help="音频文件路径，默认为空。")
    parser.add_argument("-o", "--output_path", type=str, default="output", help="输出文件路径，默认为空。")
    parser.add_argument("-t", "--target_duration", type=int, default=15, help="目标视频片段长度（秒），默认为15秒。")
    parser.add_argument("-vw", "--width", type=int, default=1280, help="输出视频宽度，默认为1280像素。")
    parser.add_argument("-vh", "--height", type=int, default=720, help="输出视频高度，默认为720像素。")
    parser.add_argument("-qv", "--quality", type=int, default=3, help="视频质量，默认为3。")
    args = parser.parse_args()

    # 替换以下占位符为实际文件夹路径
    input_directory = args.video_path
    input_audio_directory = args.audio_path
    output_directory = args.output_path

    # 确保文件夹路径有效
    if not os.path.exists(input_directory):
        raise FileNotFoundError(f"视频文件夹不存在：{input_directory}")

    if is_empty_directory(input_directory):
        raise ValueError(f"视频文件夹为空：{input_directory}")

    if not os.path.exists(input_audio_directory):
        raise FileNotFoundError(f"音频文件夹不存在：{input_audio_directory}")

    if is_empty_directory(input_audio_directory):
        raise ValueError(f"音频文件夹为空：{input_audio_directory}")

    if not os.path.exists(output_directory):
        os.makedirs(output_directory)



    # ----------------------合成音频----------------------------------------------------
    audio_files = [f for f in os.listdir(input_audio_directory) if f.endswith(('.mp4','.mp3', '.wav'))]

    # 挑选出能满足长度的音频，组合起来
    selected_audio_clips = []
    # 随机挑选出来的音频长度
    total_audio_duration = 0

    final_audio_clip = None
    while total_audio_duration< args.target_duration:
        audio_file = random.choice(audio_files)
        audio_path = os.path.join(input_audio_directory, audio_file)
        audio_clip = AudioFileClip(audio_path)

        tmp_total_audio_duration = total_audio_duration + audio_clip.duration
        if tmp_total_audio_duration <= args.target_duration:
            selected_audio_clips.append(audio_clip)
            total_audio_duration += audio_clip.duration
        else:
            #超出部分直接裁剪
            rest_duration = args.target_duration-total_audio_duration
            tmp_audio_clip = audio_clip.subclip(0, rest_duration)
            selected_audio_clips.append(tmp_audio_clip)
            total_audio_duration += tmp_audio_clip.duration
            break

    # 将随机挑选的音频片段组合成一个指定长度的音频片段
    for audio_clip in selected_audio_clips:
        if final_audio_clip is None:
            final_audio_clip = audio_clip
        else:
            final_audio_clip = concatenate_audioclips([final_audio_clip, audio_clip])

    # 如果总长度不足目标长度，从最后一个片段中提取剩余的长度
    if total_audio_duration< args.target_duration and len(selected_audio_clips) > 0:
        last_audio_clip = selected_audio_clips[-1]

        missing_duration = args.target_duration - total_audio_duration
        last_audio_clip = last_audio_clip.subclip(0, min(missing_duration, last_audio_clip.duration))
        final_audio_clip = concatenate_audioclips([final_audio_clip, last_audio_clip])

    print("总片段时长",final_audio_clip.duration)
    # ----------------------合成视频----------------------------------------------------
    # 从目录中随机挑选出几个片段，直到总长度达到目标长度
    # 获取目录中的所有视频文件
    video_files = [f for f in os.listdir(input_directory) if f.endswith(('.mp4', '.avi', '.mkv'))]

    selected_video_files = []
    total_duration = 0
    while total_duration< args.target_duration:
        video_file = random.choice(video_files)
        video_path = os.path.join(input_directory, video_file)
        video_clip = VideoFileClip(video_path)

        if total_duration + video_clip.duration <= args.target_duration:
            selected_video_files.append(video_file)
            total_duration += video_clip.duration
        else:
            break

    # 将随机挑选的片段组合成一个指定长度的视频片段
    final_clip = None
    for video_file in selected_video_files:
        video_path = os.path.join(input_directory, video_file)
        video_clip = VideoFileClip(video_path)

        if final_clip is None:
            final_clip = video_clip
        else:
            final_clip = concatenate_videoclips([final_clip, video_clip])

    # 如果总长度不足目标长度，从最后一个片段中提取剩余的长度
    if total_duration< args.target_duration:
        last_video_file = selected_video_files[-1]
        last_video_path = os.path.join(input_directory, last_video_file)
        last_video_clip = VideoFileClip(last_video_path)

        missing_duration = args.target_duration - total_duration
        last_video_clip = last_video_clip.subclip(0, min(missing_duration, last_video_clip.duration))
        final_clip = concatenate_videoclips([final_clip, last_video_clip])

    # 将音频片段添加到视频片段中
    final_clip = final_clip.set_audio(final_audio_clip)
    # 调整视频宽度和高度
    final_clip = final_clip.resize((args.width, args.height))



    # 设置preset值以控制编码速度和压缩效果
    preset_values=["ultrafast","superfast","veryfast","faster","fast","medium","slow","slower","veryslow"]
    preset_index=args.quality
    if preset_index<0 or preset_index>=len(preset_values):
        preset_index=len(preset_values)-1
    preset_value=preset_values[preset_index]
    print("视频质量：",preset_value)

    # 保存组合后的视频片段到指定目录
    current_time = datetime.now().strftime("%Y%m%d%H%M%S")
    output_filename = f"{current_time}_{args.target_duration}s_{preset_value}_{args.width}x{args.height}.mp4"
    output_path = os.path.join(output_directory, output_filename)


    # 保存组合后的视频片段到指定目录
    final_clip.write_videofile(output_path, codec='libx264',preset=preset_value)

    print("已生成组合视频：",output_filename)

# 视频相关方法------------------------------------------------------------------------------------------------------
# 视频片段提取
def video_extract(video_clip,start_time,end_time):
    return video_clip.subclip(start_time, end_time)

# 视频片段写入
def video_write(video_clip,output_path,preset_value):
    video_clip.write_videofile(output_path, codec='libx264',preset=preset_value)

# 视频片段调整分辨率
def video_resize(video_clip,width,height):
    return video_clip.resize((width, height))

# 视频片段添加字幕
def video_create_caption(text,start_time,end_time,pos_y):
    text_duration = end_time - start_time
    subtitle_clip = TextClip(text, font='FangSong', fontsize=80, color='white')
    subtitle_clip = subtitle_clip.set_start(start_time)
    subtitle_clip = subtitle_clip.set_end(end_time)
    subtitle_clip = subtitle_clip.set_duration(text_duration)
    subtitle_clip = subtitle_clip.set_position(("center", pos_y))
    return subtitle_clip


# 解析JSON文件，返回JSON数据
def parse_json_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as file:
        json_data = json.load(file)
    return json_data

# 解析JSON字符串，返回JSON数据
def parse_json_string(json_string):
    json_data = json.loads(json_string)
    return json_data

